<template>
	<div class="pitch-monitoring-page">
    <!-- 页面头部 -->
    <van-nav-bar 
      title="🎵 音高监测" 
      left-text="返回" 
      left-arrow 
      @click-left="goBack"
    />

    <!-- 处理模式选择 -->
    <van-cell-group title="处理模式" class="mode-section">
      <van-radio-group v-model="processingMode" @change="handleModeChange">
        <van-cell-group>
          <van-cell 
            title="手动上传音频文件" 
            clickable 
            @click="processingMode = 'upload'"
          >
            <template #right-icon>
              <van-radio name="upload" />
            </template>
          </van-cell>
          <van-cell 
            title="自动批量检测服务器音频" 
            clickable 
            @click="processingMode = 'auto'"
          >
            <template #right-icon>
              <van-radio name="auto" />
            </template>
          </van-cell>
        </van-cell-group>
      </van-radio-group>
    </van-cell-group>

    <!-- 手动上传模式 -->
    <van-cell-group v-if="processingMode === 'upload'" title="音频文件上传" class="upload-section">
      <van-uploader
        v-model="fileList"
        :after-read="handleFileChange"
        accept="audio/*"
        :max-count="1"
        upload-text="选择音频文件"
      />
      
      <!-- 音频信息显示 -->
      <van-cell-group v-if="audioInfo" title="音频信息">
        <van-cell title="文件名" :value="audioInfo.fileName" />
        <van-cell title="时长" :value="formatDuration(audioInfo.duration)" />
        <van-cell title="采样率" :value="audioInfo.sampleRate + ' Hz'" />
        <van-cell title="声道数" :value="audioInfo.numberOfChannels" />
      </van-cell-group>

      <!-- 时间区间设置 -->
      <van-cell-group v-if="audioInfo" title="检测时间区间">
        <van-field
          v-model.number="startTime"
          type="number"
          label="开始时间(秒)"
          placeholder="请输入开始时间"
						:min="0" 
          :max="audioInfo.duration"
          step="0.1"
        />
        <van-field
          v-model.number="endTime"
          type="number"
          label="结束时间(秒)"
          placeholder="请输入结束时间"
          :min="startTime"
          :max="audioInfo.duration"
          step="0.1"
        />
        <van-field
          v-model.number="intervalMs"
          type="number"
          label="检测间隔(毫秒)"
          placeholder="请输入检测间隔"
          :min="10"
          :max="1000"
          step="10"
        />
      </van-cell-group>

      <!-- 开始检测按钮 -->
      <div class="analyze-button">
        <van-button
          type="primary"
          size="large"
          :loading="isAnalyzing"
          :disabled="!canAnalyze"
          @click="analyzePitch"
          block
        >
          开始检测音高
        </van-button>
			</div>
    </van-cell-group>

    <!-- 自动批量检测模式 -->
    <van-cell-group v-if="processingMode === 'auto'" title="自动批量检测" class="auto-section">
      <van-button
        type="primary"
        size="large"
        :loading="isScanning"
        @click="scanServerFiles"
        block
        style="margin-bottom: 16px;"
      >
        扫描音频文件
      </van-button>

      <!-- 服务器音频文件列表 -->
      <div v-if="serverFiles.length > 0">
        <van-notice-bar
          :text="`发现 ${serverFiles.length} 个音频文件`"
          type="success"
          left-icon="info-o"
        />

        <van-button
          type="primary"
          size="large"
          :loading="isBatchProcessing"
          :disabled="serverFiles.length === 0"
          @click="startBatchDetection"
          block
          style="margin: 16px 0;"
        >
          开始批量检测 ({{ serverFiles.length }} 个文件)
        </van-button>

        <!-- 进度条 -->
        <van-progress
          v-if="batchProgress.total > 0"
          :percentage="Math.round((batchProgress.current / batchProgress.total) * 100)"
          :show-pivot="true"
          :pivot-text="`${batchProgress.current}/${batchProgress.total}`"
        />

        <!-- 当前处理文件信息 -->
        <van-cell-group v-if="currentProcessingFile" title="当前处理文件">
          <van-cell title="文件名" :value="currentProcessingFile.name" />
          <van-cell title="大小" :value="formatFileSize(currentProcessingFile.size)" />
          <van-cell title="格式" :value="currentProcessingFile.extension.toUpperCase()" />
          <van-cell title="状态">
            <template #value>
              <van-tag :type="getProcessingStatusType(currentProcessingFile.status)">
                {{ currentProcessingFile.status }}
              </van-tag>
            </template>
          </van-cell>
        </van-cell-group>

        <!-- 文件列表 -->
        <van-collapse v-model="activeCollapse">
          <van-collapse-item title="查看文件列表" name="fileList">
            <van-list>
              <van-cell
                v-for="file in serverFiles"
                :key="file.name"
                :title="file.name"
                :label="`${formatFileSize(file.size)} - ${file.extension.toUpperCase()}`"
              >
                <template #right-icon>
                  <van-tag :type="getProcessingStatusType(file.status)" size="small">
                    {{ file.status || '待处理' }}
                  </van-tag>
                </template>
              </van-cell>
            </van-list>
          </van-collapse-item>
        </van-collapse>
		</div>

      <!-- 无文件提示 -->
      <van-empty
        v-else-if="!isScanning"
        image="search"
        description="未发现音频文件"
      >
        <van-button type="primary" @click="scanServerFiles">重新扫描</van-button>
      </van-empty>
    </van-cell-group>

    <!-- 检测结果 -->
    <van-cell-group v-if="allResults.length > 0" title="检测结果" class="results-section">
      <template #title>
        <div class="results-header">
          <span>检测结果</span>
          <div class="results-stats">
            <van-tag type="info" size="small">
              {{ processingMode === 'auto' ? `${processedFiles.length} 个文件` : '单文件' }}
            </van-tag>
            <van-tag type="success" size="small">
              {{ allResults.length }} 个数据点
            </van-tag>
			</div>
		</div>
      </template>

      <!-- 结果统计 -->
      <van-grid :column-num="2" :border="false">
        <van-grid-item>
          <div class="stat-item">
            <div class="stat-value">{{ results.length }}</div>
            <div class="stat-label">检测点数</div>
          </div>
        </van-grid-item>
        <van-grid-item>
          <div class="stat-item">
            <div class="stat-value">{{ averageFrequency.toFixed(1) }}</div>
            <div class="stat-label">平均频率(Hz)</div>
			</div>
        </van-grid-item>
        <van-grid-item>
          <div class="stat-item">
            <div class="stat-value">{{ maxFrequency.toFixed(1) }}</div>
            <div class="stat-label">最高频率(Hz)</div>
			</div>
        </van-grid-item>
        <van-grid-item>
          <div class="stat-item">
            <div class="stat-value">{{ minFrequency.toFixed(1) }}</div>
            <div class="stat-label">最低频率(Hz)</div>
			</div>
        </van-grid-item>
      </van-grid>

      <!-- 操作按钮 -->
      <div class="results-actions">
        <van-button
          v-if="processingMode === 'auto'"
          type="warning"
          size="small"
          @click="clearAllResults"
          style="margin-right: 8px;"
        >
          清空结果
        </van-button>
        <van-button
          type="success"
          size="small"
          @click="exportResults"
        >
          导出结果
        </van-button>
		</div>

		<!-- 结果列表 -->
      <van-list
        v-model:loading="loading"
        :finished="finished"
        finished-text="没有更多了"
        @load="onLoad"
      >
        <van-cell
          v-for="(result, index) in paginatedResults"
					:key="index"
          :title="`${result.frequency.toFixed(2)} Hz`"
          :label="`时间: ${result.time.toFixed(2)}s`"
        >
          <template #value>
            <div class="result-content">
              <van-tag type="primary" size="small">{{ result.noteName.note }}</van-tag>
              <van-tag type="success" size="small">{{ result.noteName.octave }}</van-tag>
              <van-tag type="info" size="small">{{ result.noteName.fullName }}</van-tag>
					</div>
            <div class="result-meta">
              <van-tag :type="getConfidenceType(result.confidence)" size="small">
                {{ formatConfidence(result.confidence) }}
              </van-tag>
              <span class="method-text">{{ result.method }}</span>
					</div>
            <div v-if="result.noteName.cents !== undefined" class="cents-info">
              <span :style="{ color: Math.abs(result.noteName.cents) > 30 ? '#f56c6c' : '#67c23a' }">
                {{ result.noteName.cents > 0 ? '+' : '' }}{{ result.noteName.cents }}¢
              </span>
					</div>
          </template>
        </van-cell>
      </van-list>
    </van-cell-group>

		<!-- 错误提示 -->
    <van-notify v-model:show="showError" type="danger" message="检测失败" />
	</div>
</template>

<script setup>
import { ref, computed, watch } from 'vue'
import { AdvancedPitchDetector } from '@/utils/advancedPitchDetection.js'
import { Toast, Dialog } from 'vant'

// 响应式数据
const processingMode = ref('upload') // 'upload' | 'auto'
const fileList = ref([])
const audioInfo = ref(null)
const startTime = ref(0)
const endTime = ref(0)
const intervalMs = ref(20)
const isAnalyzing = ref(false)
const results = ref([]) // 单文件结果
const allResults = ref([]) // 所有文件的结果

// 批量处理相关
const serverFiles = ref([])
const isScanning = ref(false)
const isBatchProcessing = ref(false)
const batchProgress = ref({ current: 0, total: 0 })
const currentProcessingFile = ref(null)
const processedFiles = ref([])
const activeCollapse = ref([])

// 分页相关
const loading = ref(false)
const finished = ref(false)
const currentPage = ref(1)
const pageSize = ref(20)

// 错误处理
const showError = ref(false)
const errorMessage = ref('')

// API基础地址
const API_BASE = 'http://localhost:3001'

// 音高检测器实例
const pitchDetector = new AdvancedPitchDetector()

// 计算属性
const canAnalyze = computed(() => {
  return audioInfo.value && startTime.value < endTime.value && !isAnalyzing.value
})

const paginatedResults = computed(() => {
  const start = (currentPage.value - 1) * pageSize.value
  const end = start + pageSize.value
  return allResults.value.slice(start, end).map((item, index) => ({
    ...item,
    index: start + index + 1
  }))
})

const averageFrequency = computed(() => {
  if (allResults.value.length === 0) return 0
  const validResults = allResults.value.filter(r => r.frequency > 0)
  if (validResults.length === 0) return 0
  return validResults.reduce((sum, r) => sum + r.frequency, 0) / validResults.length
})

const maxFrequency = computed(() => {
  if (allResults.value.length === 0) return 0
  return Math.max(...allResults.value.map(r => r.frequency))
})

const minFrequency = computed(() => {
  if (allResults.value.length === 0) return 0
  const validResults = allResults.value.filter(r => r.frequency > 0)
  if (validResults.length === 0) return 0
  return Math.min(...validResults.map(r => r.frequency))
})

// 监听时间变化
watch(audioInfo, (newInfo) => {
  if (newInfo) {
    startTime.value = 0
    endTime.value = Math.min(10, newInfo.duration) // 默认检测前10秒
  }
})

// 方法函数
const goBack = () => {
  // 返回上一页的逻辑
  window.history.back()
}

// 模式切换处理
const handleModeChange = (mode) => {
  if (mode === 'auto') {
    // 切换到自动模式时，自动扫描文件
    scanServerFiles()
	} else {
    // 切换到手动模式时，清空服务器文件列表
    serverFiles.value = []
    currentProcessingFile.value = null
  }
}

// 文件上传处理
const handleFileChange = async (file) => {
  if (!file.file) {
    Toast('请选择音频文件')
    return
  }

  // 检查文件类型
  if (!file.file.type.startsWith('audio/')) {
    Toast('请上传音频文件')
    return
  }

  try {
    Toast('正在加载音频文件...')
    
    const info = await pitchDetector.loadAudioFile(file.file)
    audioInfo.value = {
      fileName: file.file.name,
      ...info
    }
    
    // 清空之前的结果
    results.value = []
    allResults.value = []
    currentPage.value = 1
    
    Toast('音频文件加载成功')
  } catch (error) {
    console.error('加载音频文件失败:', error)
    Toast('加载音频文件失败，请确保文件格式正确')
  }
}

// 开始音高检测
const analyzePitch = async () => {
  if (!canAnalyze.value) return

  isAnalyzing.value = true
  results.value = []
  if (processingMode.value === 'upload') {
    allResults.value = []
  }
  currentPage.value = 1

  try {
    Toast('正在分析音高，请稍候...')
    
    const analysisResults = await pitchDetector.analyzePitchInTimeRange(
      startTime.value,
      endTime.value,
      intervalMs.value
    )
    
    results.value = analysisResults
    allResults.value = analysisResults
    Toast(`音高分析完成，共检测到 ${analysisResults.length} 个数据点`)
  } catch (error) {
    console.error('音高分析失败:', error)
    Toast('音高分析失败: ' + error.message)
  } finally {
    isAnalyzing.value = false
  }
}

// 扫描服务器音频文件
const scanServerFiles = async () => {
  isScanning.value = true
  try {
    const response = await fetch(`${API_BASE}/api/audio-files`)
    const data = await response.json()
    
    if (response.ok) {
      serverFiles.value = data.files.map(file => ({
        ...file,
        status: '待处理'
      }))
      Toast(data.message)
    } else {
      Toast(data.message || '扫描文件失败')
    }
  } catch (error) {
    console.error('扫描文件失败:', error)
    Toast('无法连接到服务器，请确保后端服务已启动')
  } finally {
    isScanning.value = false
  }
}

// 开始批量检测
const startBatchDetection = async () => {
  if (serverFiles.value.length === 0) return
  
  isBatchProcessing.value = true
  batchProgress.value = { current: 0, total: serverFiles.value.length }
  allResults.value = [] // 清空之前的结果
  processedFiles.value = []
  
  try {
    for (let i = 0; i < serverFiles.value.length; i++) {
      const file = serverFiles.value[i]
      currentProcessingFile.value = { ...file, status: '正在处理' }
      
      try {
        // 更新状态
        file.status = '正在处理'
        
        // 从服务器加载音频文件
        const audioUrl = `${API_BASE}${file.url}`
        const response = await fetch(audioUrl)
        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`)
        }
        
        const audioBlob = await response.blob()
        const audioFile = new File([audioBlob], file.name, { type: audioBlob.type })
        
        // 加载音频到检测器
        const audioInfo = await pitchDetector.loadAudioFile(audioFile)
        
        // 检测整个音频文件（从开始到结束）
        const analysisResults = await pitchDetector.analyzePitchInTimeRange(
          0, // 从开始
          audioInfo.duration, // 到结束
          intervalMs.value
        )
        
        // 为每个结果添加文件名
        const resultsWithFilename = analysisResults.map(result => ({
          ...result,
          filename: file.name
        }))
        
        // 添加到总结果中
        allResults.value.push(...resultsWithFilename)
        
        // 更新处理状态
        file.status = '已完成'
        batchProgress.value.current = i + 1
        processedFiles.value.push(file.name)
        
        Toast(`${file.name} 处理完成，检测到 ${analysisResults.length} 个数据点`)
        
      } catch (error) {
        console.error(`处理文件 ${file.name} 失败:`, error)
        file.status = '处理失败'
        Toast(`处理文件 ${file.name} 失败: ${error.message}`)
        batchProgress.value.current = i + 1
      }
    }
    
    Toast(`批量处理完成！共处理 ${processedFiles.value.length} 个文件，检测到 ${allResults.value.length} 个数据点`)
    
  } catch (error) {
    console.error('批量处理失败:', error)
    Toast('批量处理失败: ' + error.message)
  } finally {
    isBatchProcessing.value = false
    currentProcessingFile.value = null
  }
}

// 清空所有结果
const clearAllResults = async () => {
  try {
    await Dialog.confirm({
      title: '确认清空',
      message: '确定要清空所有检测结果吗？此操作无法撤销。',
    })
    allResults.value = []
    processedFiles.value = []
    currentPage.value = 1
    Toast('已清空所有结果')
  } catch {
    // 用户取消
  }
}

// 导出结果
const exportResults = () => {
  if (allResults.value.length === 0) {
    Toast('没有检测结果可导出')
    return
	}
	
	try {
		// 创建CSV内容
    const headers = processingMode.value === 'auto' 
      ? ['序号', '文件名', '时间(秒)', '频率(Hz)', '音名', '组别', '完整音名', '置信度', '检测方法', '音分偏差']
      : ['序号', '时间(秒)', '频率(Hz)', '音名', '组别', '完整音名', '置信度', '检测方法', '音分偏差']
    
		const csvContent = [
			headers.join(','),
      ...allResults.value.map((item, index) => {
        const baseData = [
          index + 1,
          item.time.toFixed(2),
          item.frequency.toFixed(2),
          item.noteName.note,
          item.noteName.octave,
          item.noteName.fullName,
          formatConfidence(item.confidence),
          item.method || 'unknown',
          item.noteName.cents !== undefined ? item.noteName.cents : ''
        ]
        
        if (processingMode.value === 'auto') {
          return [index + 1, item.filename || 'unknown', ...baseData.slice(1)].join(',')
        } else {
          return baseData.join(',')
        }
      })
    ].join('\n')
		
		// 创建下载链接
    const blob = new Blob(['\ufeff' + csvContent], { type: 'text/csv;charset=utf-8;' })
    const link = document.createElement('a')
    link.href = URL.createObjectURL(blob)
    link.download = `音高检测结果_${new Date().toISOString().slice(0, 19).replace(/:/g, '-')}.csv`
    link.click()

    Toast('结果导出成功')
  } catch (error) {
    console.error('导出失败:', error)
    Toast('导出失败')
  }
}

// 格式化函数
const formatDuration = (seconds) => {
  const minutes = Math.floor(seconds / 60)
  const remainingSeconds = Math.floor(seconds % 60)
  return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`
}

const formatFileSize = (bytes) => {
  if (bytes === 0) return '0 B'
  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}

const formatConfidence = (confidence) => {
  if (confidence <= 1) {
    return (confidence * 100).toFixed(1) + '%'
  } else {
    // 对于大于1的值，映射到0-100%范围
    const normalized = Math.min(100, Math.max(0, (confidence / 10) * 100))
    return normalized.toFixed(1) + '%'
  }
}

const getConfidenceType = (confidence) => {
  let normalizedConfidence = confidence
  if (confidence > 1) {
    normalizedConfidence = Math.min(1, confidence / 10)
  }
  
  if (normalizedConfidence > 0.7) return 'success'
  if (normalizedConfidence > 0.4) return 'warning'
  return 'danger'
}

const getProcessingStatusType = (status) => {
  switch (status) {
    case '已完成': return 'success'
    case '正在处理': return 'warning'
    case '处理失败': return 'danger'
    default: return 'info'
  }
}

// 分页加载
const onLoad = () => {
  // 模拟异步加载
  setTimeout(() => {
    loading.value = false
    if (currentPage.value * pageSize.value >= allResults.value.length) {
      finished.value = true
    } else {
      currentPage.value++
    }
  }, 1000)
}
</script>

<style scoped>
.pitch-monitoring-page {
  background-color: #f8f9fa;
  min-height: 100vh;
}

.mode-section,
.upload-section,
.auto-section,
.results-section {
  margin-bottom: 16px;
}

.results-header {
	display: flex;
	justify-content: space-between;
	align-items: center;
  width: 100%;
}

.results-stats {
  display: flex;
  gap: 8px;
}

.analyze-button {
  padding: 16px;
}

.stat-item {
  text-align: center;
  padding: 8px;
}

.stat-value {
  font-size: 18px;
  font-weight: bold;
  color: #1989fa;
  margin-bottom: 4px;
}

.stat-label {
  font-size: 12px;
  color: #969799;
}

.results-actions {
  padding: 16px;
  display: flex;
  justify-content: center;
}

.result-content {
  display: flex;
  gap: 4px;
  margin-bottom: 4px;
}

.result-meta {
	display: flex;
	align-items: center;
  gap: 8px;
  margin-bottom: 4px;
}

.method-text {
  font-size: 12px;
  color: #969799;
}

.cents-info {
  font-size: 12px;
	font-weight: bold;
}

/* 自定义样式覆盖 */
:deep(.van-cell-group__title) {
  font-weight: 600;
  color: #323233;
}

:deep(.van-radio-group) {
  width: 100%;
}

:deep(.van-uploader__wrapper) {
  width: 100%;
}

:deep(.van-uploader__upload) {
  width: 100%;
  height: 80px;
  border: 2px dashed #dcdee0;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: #fafafa;
}

:deep(.van-uploader__upload-text) {
  color: #969799;
  font-size: 14px;
}

:deep(.van-grid-item__content) {
  padding: 8px;
}

:deep(.van-list) {
  max-height: 400px;
  overflow-y: auto;
}
</style>